<?php

namespace app\api\http;

use GatewayWorker\Lib\Gateway;
use Workerman\Worker;
use think\worker\Application; // 特别注意：下方用到的Application属于think\work命名空间下的类，由于命名空间的更换，需要这样引入才能使用，否则会报错找不到这个类。
use think\facade\Db;
use app\common\util\JwtUtil;
use Exception;

/**
 * Worker 命令行服务类 php think worker:gateway  -d/stop 守护/停止
 */
class Events
{
  /**
   * onWorkerStart 事件回调
   * 当businessWorker进程启动时触发。每个进程生命周期内都只会触发一次
   *
   * @access public
   * @param  \Workerman\Worker    $businessWorker
   * @return void
   */
  public static function onWorkerStart(Worker $businessWorker)
  {
    $app = new Application;
    $app->initialize();
  }

  /**
   * onConnect 事件回调
   * 当客户端连接上gateway进程时(TCP三次握手完毕时)触发
   *
   * @access public
   * @param  int       $client_id
   * @return void
   */
  public static function onConnect($client_id)
  {
    // Gateway::sendToCurrentClient("Your client_id is $client_id");
    $res = [
      'type' => 'connect',
      'client_id' => $client_id
    ];
    // 向当前client_id发送数据 
    Gateway::sendToClient($client_id, json_encode($res, true));
  }

  /**
   * onWebSocketConnect 事件回调
   * 当客户端连接上gateway完成websocket握手时触发
   *
   * @param  integer  $client_id 断开连接的客户端client_id
   * @param  mixed    $data
   * @return void
   */
  public static function onWebSocketConnect($client_id, $data)
  {
    var_export($data);
  }

  /**
   * onMessage 事件回调
   * 当客户端发来数据(Gateway进程收到数据)后触发
   * 注意：能操作数据库，尽量不要去调用模型，只用到thinkphp 的 Db
   * @access public
   * @param  int       $client_id
   * @param  mixed     $data
   * @return void
   */
  public static function onMessage($client_id, $data)
  {
    try {
      $form = json_decode($data, true);
      if (isset($form['type']) && !empty($form['type'])) {
        switch ($form['type']) {
          case 'ping': //轮巡消息
            $res = [
              'type' => 'ping',
              'status' => 'keep connection.'
            ];
            Gateway::sendToClient($client_id, json_encode($res, true));
            // to do ... 要发给客户端用户的
            break;
          case 'bind': //绑定
            if (isset($form['formId'])) {
              if (isset($form['token']) && !empty($form['token'])) {
                $payload = JwtUtil::decode($form['token']);
                if (empty($payload) || empty($payload['uid']) || empty($payload['last_time'])) {
                  Gateway::sendToClient($client_id, '哪凉快哪呆去！');
                  return;
                }
                if ($payload['uid'] != $form['formId']) {
                  Gateway::sendToClient($client_id, '大师有失身份啊！');
                  return;
                }
              } else {
                Gateway::sendToClient($client_id, '您未登录');
                return;
              }
              $res = [
                'type' => 'bind',
                'formId' => $form['formId']
              ];
              // 判断是否已登录的用户 token
              // to do....
              // 将当前链接与uid绑定
              Gateway::bindUid($client_id, $form['formId']);
              Gateway::sendToClient($client_id, json_encode($res, true)); //通知当前客户端已绑定，可以初始化
              // 上线
              Db::name('sys_user')->where('id', $form['formId'])->update(['online' => 1, 'client_id' => $client_id]);
              //加入群聊--所有群
              $ret = Db::name('im_group_user')->where('uid', $form['formId'])->select();
              if ($ret) {
                foreach ($ret as $key => $vo) {
                  Gateway::joinGroup($client_id, $vo['group_id']); //将登录用户加入群组
                }
              }
            }
            break;
            // case 'hiscount': //多少条未读
            //   if (isset($form['formId']) && !empty($form['formId'])) {
            //     //查询有无需要推送的离线信息
            //     $time = time() - 2592000; //30天内，超过不处理--防止数据表太大，爆掉
            //     $where = [];
            //     $where[] = ['rece_id', '=', $form['formId']]; // 我接收的，全部推过来
            //     $where[] = ['create_time', '>', $time];
            //     $where[] = ['is_send', '<>', 1];
            //     $resMsg = Db::name('im_chatlog')->where($where)->count();
            //     if ($resMsg) {
            //       $log_message = [
            //         'type' => 'hiscount',
            //         'formId' => $form['formId'],
            //         'count' => $resMsg
            //       ];
            //       //批量推送
            //       Gateway::sendToUid($form['formId'], json_encode($log_message, true));
            //     }
            //   }
            //   break;
          case 'hisnosend': //历史记录
            //聊天的离线
            if (isset($form['formId']) && !empty($form['formId'])) {
              //查询有无需要推送的离线信息
              $time = time() - 2592000; //30天内，超过不处理--防止数据表太大，爆掉
              $where = [];
              $where[] = ['rece_id', '=', $form['formId']]; // 我接收的，全部推过来
              $where[] = ['create_time', '>', $time];
              $where[] = ['is_send', '<>', 1];
              $resMsg = Db::name('im_chatlog')->where($where)->select();
              if ($resMsg) {
                $log_message = [
                  'type' => 'logMessage',
                  'formId' => $form['formId'],
                  'list' => $resMsg
                ];
                //批量推送
                Gateway::sendToUid($form['formId'], json_encode($log_message, true));
                //设置推送状态为已经推送
                Db::name('im_chatlog')->where($where)->update(['is_send' => 1]);
              }
            }
            break;
          case 'flowhis': //推送的离线信息
            if (isset($form['formId']) && !empty($form['formId'])) {
              //查询有无需要推送的离线信息
              $time = time() - 2592000; //30天内，超过不处理
              $where = [];
              $where[] = ['m.rece_id', '=', $form['formId']]; // 我接收的，全部推过来
              $where[] = ['m.create_time', '>', $time];
              $resMsg = Db::name('pmm_message')->alias('m')
                ->leftjoin('pmm_flow_bill b', 'm.m_id=b.id')
                ->field('m.*,b.put_uid,b.put_name,b.put_dept_id,b.put_dept_id_name,b.flow_brief,b.now_audit_name,b.now_audit_id')
                ->where($where)->select();
              $sysMsg = Db::name('im_message')->where([
                ['create_time', '>', $time],
                ['rece_id', '=', $form['formId']],
                ['is_send', '<>', 3],
              ])->select();
              $log_message = [
                'type' => 'flowhis',
                'formId' => $form['formId'],
                'list' => [],
                'sysmsg' => []
              ];
              if ($resMsg) {
                $log_message['list'] = $resMsg;
              }
              if ($sysMsg) {
                $log_message['sysmsg'] = $sysMsg;
              }
              //推送
              Gateway::sendToUid($form['formId'], json_encode($log_message, true));
            }
            break;
          case 'chat': //聊天
            if (
              isset($form['formId']) && !empty($form['formId']) &&
              isset($form['chat_type']) && !empty($form['chat_type']) &&
              isset($form['contype']) && !empty($form['contype'])
            ) {
              $send = Db::name('sys_user')->field('id,un,real_name,avatar')->where('id', $form['formId'])->where('status', 1)->find();
              if (!$send) { //不存在
                return;
              }
              $chat_type = (int)$form['chat_type'];
              if ($chat_type == 1) {
                if (isset($form['toId']) && !empty($form['toId'])) {
                  if ($form['formId'] == $form['toId']) {
                    return; //不能自个发给自个
                  }
                  $rece = Db::name('sys_user')->field('id,un,real_name,avatar')->where('id', $form['toId'])->where('status', 1)->find();
                  if (!$rece) { //不存在
                    return;
                  }
                } else { //缺参
                  return;
                }
              }
              if ($chat_type == 2) {
                if (isset($form['group_id']) && !empty($form['group_id'])) {
                  $group = Db::name('im_group')->field('id,name,chat_head')->where('id', $form['group_id'])->where('status', 1)->find();
                  if (!$group) { //不存在
                    return;
                  }
                } else { //缺参
                  return;
                }
                // 找出群里所有人uid
                $group_uids = Db::name('im_group_user')->where('group_id', $group['id'])->column('uid');
                if (!$group_uids) { //没人
                  return;
                }
              }

              // 保存聊天记录
              $saveData = [
                'send_id' => $send['id'],
                'send_id_name' => $send['real_name'] ? $send['real_name'] : $send['un'],
                'send_id_avatar' => _img($send['avatar']),
                'rece_id' => $chat_type == 1 ? $rece['id'] : 0,
                'rece_id_name' => $chat_type == 1 ? ($rece['real_name'] ? $rece['real_name'] : $rece['un']) : '',
                'rece_id_avatar' => $chat_type == 1 ? _img($rece['avatar']) : '',
                'group_id' => $chat_type == 2 ? $group['id'] : 0,
                'group_id_name' => $chat_type == 2 ? $group['name'] : '',
                'group_id_avatar' => $chat_type == 2 ? _img($group['chat_head']) : '',
                'group_uid' =>  $chat_type == 2 ? implode(',', $group_uids) : '',
                'content_type' => $form['contype'],
                'content' => (isset($form['content']) && $form['content'] != '') ? $form['content'] : '',
                'files_url' => (isset($form['files_url']) && !empty($form['files_url'])) ? config('kaige.domain_name') . $form['files_url'] : '',
                'chat_type' => $form['chat_type'],
                'status' => 2,
                'is_send' => $chat_type == 2 ? 1 : 2,  //群聊默认已发送
                'group_status' => '' . $send['id'] . '', //自己发来的，读状态先加进去
                'create_time' => time(),
              ];

              $online = false;
              if ($chat_type == 1 && Gateway::isUidOnline($form['toId']) == 1) { //写这里，省去一次数据更新操作
                $online = true;
                $saveData['status'] = 1; // 群聊时没用到这个字段，所以不用判断$chat_type
              }

              //保存到数据库
              $log_id = Db::name('im_chatlog')->strict(false)->insertGetId($saveData);
              //拼给用户
              $saveData['id'] = $log_id;
              $saveData['type'] = 'chat';
              $saveData['time'] = $saveData['create_time'];
              //如果群聊
              if ($chat_type == 2) {
                Gateway::sendToGroup($form['group_id'], json_encode($saveData, true));
              } elseif ($chat_type == 1) { //单聊
                //如果在线，发给对方
                if ($online) {
                  Gateway::sendToUid($form['toId'], json_encode($saveData, true));
                }
                //发给自已
                Gateway::sendToUid($form['formId'], json_encode($saveData, true));
              }
            }
            break;
          case 'readreceipt': //已读
            $re = '';
            if ($form['chat_type'] && $form['formId'] && $form['toId']) {
              if ($form['chat_type'] == 1) {
                $sql = 'UPDATE ' . env('database.prefix') . 'im_chatlog SET status=1 WHERE (rece_id=' . $form['formId'] . ' AND send_id=' . $form['toId'] . ') OR (send_id=' . $form['formId'] . ' AND rece_id=' . $form['toId'] . ')';
                Db::query($sql);
              } elseif ($form['chat_type'] == 2) {
                $sql = 'SELECT * FROM sz_im_chatlog WHERE group_id=' . $form['toId'] . ' AND FIND_IN_SET(' . $form['formId'] . ',group_status)=0';
                $elist = Db::query($sql);
                if ($elist) {
                  foreach ($elist as $k => $v) {
                    if ($v['group_status']) {
                      Db::name('im_chatlog')->where('id', $v['id'])->where('group_id', $form['toId'])->update(['group_status' => $v['group_status'] . ',' . $form['formId']]);
                    } else {
                      Db::name('im_chatlog')->where('id', $v['id'])->where('group_id', $form['toId'])->update(['group_status' => $v['group_status'] . $form['formId']]);
                    }
                  }
                }
              }
              Gateway::sendToUid($form['formId'], json_encode([
                'type' => 'readreceipt',
                'formId' => $form['formId'],
                'toId' => $form['toId'],
                'chat_type' => $form['chat_type']
              ], true));
            }
            break;
            // case 'flow_add': // 流程添加
            //   if (isset($form['formId'])) {
            //     Gateway::sendToUid($form['formId'], json_encode([
            //       'type' => 'flow_add',
            //       'formId' => $form['formId']
            //     ], true));
            //   }
            //   break;
        }
      }
    } catch (Exception $e) {
      echo json_encode($e);
    }
  }

  /**
   * onClose 事件回调 当用户断开连接时触发的方法
   *
   * @param  integer $client_id 断开连接的客户端client_id
   * @return void
   */
  public static function onClose($client_id)
  {
    // 离线
    Db::name('sys_user')->where('client_id', $client_id)->update(['online' => 2]);
    //GateWay::sendToAll("client[$client_id] logout\n");
  }

  /**
   * onWorkerStop 事件回调
   * 当businessWorker进程退出时触发。每个进程生命周期内都只会触发一次。
   *
   * @param  \Workerman\Worker    $businessWorker
   * @return void
   */
  public static function onWorkerStop(Worker $businessWorker)
  {
    echo "WorkerStop\n";
  }
}
